#include<stdio.h>
#include<string.h>
#include <assert.h>
#include <stdlib.h>
#define number_of_articles 4000000
#define number_of_words 4000000
#define fscanf ignoreVariable = fscanf

int ignoreVariable;
int maksWord = 0;

struct vectorInt
{
    int len ;
    int last;
    int* table;    
}
;

struct vectorShort
{
    int len ;
    int last;
    short* table;    
}
;

typedef struct vectorInt vectorInt;
typedef struct vectorShort vectorShort;

int poczatek = 0;

vectorInt vec_article[number_of_articles];  //= malloc( sizeof(vectorInt) );
vectorShort vec_position[number_of_articles]; //= malloc( number_of_articles * sizeof(vectorInt));
int  vec_last_article[number_of_articles];  //= malloc( number_of_articles * sizeof(int));

int size = 0; 

void _indeks_start()
{
    int i;
    for(i = 0 ; i < number_of_articles; i++)
        vec_last_article[i] = 0;
}

void appendInt(vectorInt* v, int number)
{

        if( v->last >= v->len )
        {
            printf("l74\n");
            exit(1);
        }
        v->table[v->last] = number;
        v->last++;        
}



/*
int _start_structure()
{
    int i;
    for(i = 0; i < number_of_articles ; i ++)
    {
        if( vec_last_article[i] != 0 )
        {
            int k;
            vec_article[i].table = malloc(vec_article[i].len * sizeof(int) );
            for(k = 0; k < vec_article[i].len ; k ++)
            {
                vec_article[i].table[k] = 0;
            }
            vec_position[i].table = malloc(vec_position[i].len * sizeof(short) );            
            for(k = 0; k < vec_position[i].len ; k ++)
            {
                vec_position[i].table[k] = 0;
            }            
            vec_last_article[i] = -1;
            vec_article[i].last = 0;
            vec_position[i].last = 0;            
        }

    }

    return 0;
}
*/


int _start_structure()
{
    int i;
    int lenArticle = 0 ;
    int lenPosition = 0 ;
    int wskaznikArticle = 0;
    int wskaznikPosition = 0;
    
    
    for(i = 0; i < number_of_articles ; i ++)
    {
        if( vec_last_article[i] != 0 )
        {
            lenArticle += vec_article[i].len;
            lenPosition += vec_position[i].len;
        }
    }
    int * tableOfArticles = malloc(lenArticle * sizeof(int) );
    short * tableOfPosition = malloc(lenPosition * sizeof(short) );    



    int k;    
    for( k = 0; k < lenArticle ; k ++ )
    {
                tableOfArticles[k] = 0;
    }
    
    for( k = 0; k < lenPosition ; k ++ )
    {
                tableOfPosition[k] = 0;
    }
                
    for(i = 0; i < number_of_articles ; i ++)
    {
        if( vec_last_article[i] != 0 )
        {
            vec_article[i].table = tableOfArticles + wskaznikArticle;
            vec_position[i].table = tableOfPosition + wskaznikPosition;
            wskaznikArticle += vec_article[i].len;
            wskaznikPosition += vec_position[i].len;            
            vec_last_article[i] = -1;
            vec_article[i].last = 0;
            vec_position[i].last = 0;            
        }

    }
    return 0;
}


int end(vectorInt *v)
{
    return v->table[v->last - 1];
}


void appendShort(vectorShort* v, int number)
{
        if( v->last >= v->len )
        {
            printf("l74\n");
            exit(1);
        }

        v->table[v->last] = number;
        v->last++;        
}


int _indeks_put(int word, int article, int position)
{
    if( position > 32000)
    {
        position = 32000;
    }
        
    if( article == 0)
    {
        printf("l78 -artykul musi byc wiekszy od zera!\n");
        exit(1);
        
    }
    if( word <= 0)
    {
        printf("l84 - slowo musi miec numer wiekszy od zera!\n");
        exit(1);
    
    }
    if(  vec_last_article[word] == 0 )
    {
        printf("%d %d %d %d %d\n",word,vec_article[word].last,vec_article[word].len,vec_position[word].last,vec_position[word].len);
        printf("l111\n");
        exit(1);
    }
    
    if( vec_last_article[word] == article )
    {
        appendShort(&vec_position[word],position);           
    } 
    else
    {
        appendInt(&vec_article[word],article);
        appendShort(&vec_position[word],-position);           
        vec_last_article[word] = article;
    }
    return 0;
}


void _indeks_serialize(char* fileName)
{
    int i;
    printf("maks word to %d\n",maksWord);
    FILE * out = fopen(fileName,"w");
    for(i = 0 ; i < number_of_articles ; i ++)
    {
        if( vec_last_article[i] != 0 )
        {
            fprintf(out,"%d\n",vec_article[i].len);
            fprintf(out,"%d\n",vec_position[i].len);                        
        }
        else
        {
            fprintf(out,"%d\n",-1);
            fprintf(out,"%d\n",-1);                                    
        }
    }
    fclose(out);
}


void _fully_indeks_serialize(char *fileName)
{
    int i;
    FILE * out = fopen(fileName,"w");
    for(i = 0 ; i < number_of_articles ; i ++)
    {
        if( vec_last_article[i] != 0 )
        {
            fprintf(out,"%d\n",vec_article[i].len);
            fprintf(out,"%d\n",vec_position[i].len);                        
        }
        else
        {
            fprintf(out,"%d\n",-1);
            fprintf(out,"%d\n",-1);                                    
        }
    }
    int k;
    for(i = 0 ; i < number_of_articles ; i ++)
    {
        if( vec_last_article[i] != 0 )
        {
            for(k = 0 ; k < vec_article[i].len ; k ++)
            {
                fprintf(out,"%d\n",vec_article[i].table[k]);
            }
            for(k = 0 ; k < vec_position[i].len ; k ++)
            {
                fprintf(out,"%d\n",vec_position[i].table[k]);
            }
        }
    
    }  
    fclose(out);
}

void _fully_indeks_deserialize(char* fileName)
{
    int i;
    FILE * out = fopen(fileName,"r");
    if( !out )
    {
        printf("indeks.c: l262. Plik do deserializacji nie istnieje!\n");
    }
    for(i = 0 ; i < number_of_articles ; i ++)
    {
        int temp;
        fscanf(out,"%d\n",&temp);
        if( temp != -1 )
        {
            vec_article[i].len = temp;
            (fscanf(out,"%d\n",&temp));            
            vec_position[i].len = temp;            
            vec_last_article[i] = 1;
    
        }   
        else
        {
            (fscanf(out,"%d\n",&temp));        
            vec_article[i].len = 0;
            vec_position[i].len = 0;            
            vec_last_article[i] = 0;
        }
    }
    /*
    if( vec_last_article[5] == 0)
    {
        printf("l142 \n");
        exit(1);
    }
    */
    _start_structure();
    
    for(i = 0 ; i < number_of_articles ; i ++)
    {
            
        if( vec_last_article[i] != 0 )
        {
            int temp;
            int k;
            for(k = 0 ; k < vec_article[i].len ; k ++)
            {
                fscanf(out,"%d\n",&temp);
                vec_article[i].table[k] = temp;
            }
            for(k = 0 ; k < vec_position[i].len ; k ++)
            {
                fscanf(out,"%d\n",&temp);
                vec_position[i].table[k] = temp;
            }
        }
    
    }
    
    fclose(out);    
}


void _indeks_deserialize(char * fileName)
{
    int i;
    FILE * in = fopen(fileName,"r");
    if( ! in )
    {
        printf("index.c: l324. Plik %s nie istnieje!\n",fileName);
        exit(1);
    }
    for(i = 0 ; i < number_of_articles ; i ++)
    {
        int temp;
        fscanf(in,"%d\n",&temp);
        if( temp != -1 )
        {
            vec_article[i].len = temp;
            fscanf(in,"%d\n",&temp);            
            vec_position[i].len = temp;            
            vec_last_article[i] = 1;
    
        }   
        else
        {
            fscanf(in,"%d\n",&temp);        
            vec_article[i].len = 0;
            vec_position[i].len = 0;            
            vec_last_article[i] = 0;
        }
    }
    /*
    if( vec_last_article[1] == 0)
    {
        printf("l142 \n");
        exit(1);
    }
    */
    fclose(in);    
}

int _mock_put(int word, int article, int position)
{
    if( word > maksWord )
    {
        maksWord = word;
    }
    if( article == 0)
    {
        printf("l338 -artykul musi byc wiekszy od zera!\n");
        exit(1);
        
    }
    if( word <= 0)
    {
        printf("%d %d\n",word,word+700000);
        printf("l344 - slowo musi miec numer wiekszy od zera!\n");
        exit(1);
    
    }    
    if( poczatek == 0)
    {
        poczatek = 1;
        _indeks_start();
    }    
    if( word >= number_of_articles - 10)
    {
        printf("l355 - za duza wartosc slowa!\n");
        exit(1);
        
    }
    
    if( vec_last_article[word] == 0 )
    {
           vec_article[word].len = 1;
           vec_position[word].len = 1;
           vec_last_article[word] = article;
                           
    }
    else if( vec_last_article[word] == article )
    {
           vec_position[word].len += 1;        
    }
    else
    {
        vec_article[word].len += 1;
        vec_position[word].len += 1;
        vec_last_article[word] = article;
    }
    return 0;
}
